#-*- encoding:utf-8 -*-
from canlib import Frame as canFrame
from canlib import canlib

# from canlib.canlib import ChannelData
from canlib import kvadblib

# canlib.canOPEN_ACCEPT_VIRTUAL     # Allow opening of virtual channels as well as physical channels.
# canlib.canOPEN_CAN_FD             # The channel will use the CAN FD protocol, ISO compliant. This also means that messages with canFDMSG_xxx flags can now be used.
# canlib.canOPEN_CAN_FD_NONISO      # The channel will use the CAN FD NON-ISO protocol. Use this if you want to configure the can controller to be able to communicate with a can controller designed prior to the release of the CAN FD ISO specification.
# canlib.canOPEN_EXCLUSIVE          # Don't allow sharing of this CANlib channel between applications.
# canlib.canOPEN_NO_INIT_ACCESS     # Don't open the handle with init access.This define is used in canOpenChannel().
# canlib.canOPEN_OVERRIDE_EXCLUSIVE # Open the channel even if it is opened for exclusive access already.
# canlib.canOPEN_REQUIRE_EXTENDED   # This flag causes two things to happen:1.The call will fail if the specified circuit doesn't allow extended CAN (CAN 2.0B).2.If no frame-type flag is specified in a call to canWrite, it is assumed that extended CAN should be used.
# canlib.canOPEN_REQUIRE_INIT_ACCESS# Fail the call if the channel cannot be opened with init access.
rt = {500:canlib.canBITRATE_500K,
    50:canlib.canBITRATE_50K,
    62:canlib.canBITRATE_62K,
    83:canlib.canBITRATE_83K,
    250:canlib.canBITRATE_250K,
    125:canlib.canBITRATE_125K,
    1000:canlib.canBITRATE_1M,
    100:canlib.canBITRATE_100K,
    10:canlib.canBITRATE_10K}

class KvDrvMgr:
    def __init__(self,rate=500):
        self.ch = None
        self.rate = None
        # init
        self.setBitrate(rate)
        self.setOpFlag()
    
    def initHW(self,channel = 0,outputControl=canlib.Driver.NORMAL):
        self.ch = canlib.openChannel(channel,canlib.canOPEN_ACCEPT_VIRTUAL)
        # self.ch.busOff()
        self.ch.setBusOutputControl(outputControl)
        self.ch.setBusParams(self.rate)
        self.ch.busOn()

    def setBitrate(self,bitrate):
        self.rate = rt[bitrate]
    
    def setOpFlag(self,flag = "default"):
        fg = {"default":"canlib.canOPEN_ACCEPT_VIRTUAL"}
        self.opFlag = fg[flag]
    def recvMsg(self):
        # set Fliter
        # ch.canAccept(0x0f0,canlib.AcceptFilterFlag.SET_MASK_STD)
        # ch.canAccept(0x0f0,canlib.AcceptFilterFlag.SET_CODE_STD)
        try:
            (msgId,msg,dlc,flg,time1) = self.ch.read(timeout = 100)
            data = ''.join(format(x,"02x") for x in msg)
            #print("time:%9d id:%9d flag:0x%02x dlc:%d data:%s" %(time1, msgId, flg, dlc, data))
        except (canlib.canNoMsg) as ex:
            pass
        except (canlib.canError) as ex:
            print(ex)
        print(time1,"\t%x\t" % msgId,data)
    def recvMsgWait(self):
        # self.ch.readSyncSpecific(id_=0x33,timeout=100)
        # self.ch.readTimer()
        pass
    def sendMsg(self,id,msg=list(),extFrm=False):
        frmtype = canlib.MessageFlag.EXT if extFrm else canlib.MessageFlag.STD
        frame = canFrame(id_=id,data=msg,flags = frmtype)
        self.ch.write(frame)

class KvDBCMgr:
    def __init__(self):
        self.namelist = list()
        self.idlist = list()
        self.db = None
    def OpenFile(self,path):
        self.db = kvadblib.Dbc(filename = path)
        framebox = kvadblib.FrameBox(path)


if __name__ == "__main__":
    import threading
    import time

    kv = KvDrvMgr()
    kv.initHW()
    kv.sendMsg(0x130,[1,2,3,4,5])
    kv.sendMsg(0x130,[1,2,3,4,5])
    kv.sendMsg(0x130,[1,2,3,4,5])
    kv.sendMsg(0x130,[1,2,3,4,5])
    kv.sendMsg(0x130,[1,2,3,4,5])
    kv.sendMsg(0x130,[1,2,3,4,5])
    for i in range(0,1000):
        kv.recvMsg()
        time.sleep(0.2)